package com.starinside.wp.service.chat;

import com.alibaba.fastjson.JSON;
import com.starinside.wp.handler.ChatKefuListener;
import com.starinside.wp.listener.OpenAIEventSourceListener;
import com.unfbx.chatgpt.entity.chat.ChatChoice;
import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
import com.unfbx.sparkdesk.SparkDeskClient;
import com.unfbx.sparkdesk.entity.*;
import com.unfbx.sparkdesk.listener.ChatListener;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.sse.EventSource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

@Service
@Slf4j
public class XFSQuestionServiceImpl implements IQuestionService {

    //常公子
    private static String APP_ID = "7d636d19";
    private static String API_KEY = "03092dbc7acf517e12fa2bde27f955b1";
    private static String API_SECRET = "OWIxZjljMDZkMjVkOWY5YjIxMjhlYmFk";

    public static final String SPARK_API_HOST_WS_V3_1 = "http://spark-api.xf-yun.com/v3.1/chat";
    public static final String SPARK_API_HOST_WSS_V3_1 = "https://spark-api.xf-yun.com/v3.1/chat";

    private static SparkDeskClient sparkDeskClient = null;
    static {
        sparkDeskClient = SparkDeskClient.builder()
//                .host(SparkDesk.SPARK_API_HOST_WS_V2_1)
                .host(SPARK_API_HOST_WS_V3_1)
                .appid(APP_ID)
                .apiKey(API_KEY)
                .apiSecret(API_SECRET)
                .build();
    }


    @Override
    public void sseQuestion(List<com.unfbx.chatgpt.entity.chat.Message> messages, OpenAIEventSourceListener listener){
        // 建议直接查看demo包代码，这里更新可能不及时
        InHeader header = InHeader.builder().uid(UUID.randomUUID().toString().substring(0, 10)).appid(APP_ID).build();

        Parameter parameter = Parameter.builder()
                .chat(Chat.builder()
                        .domain("generalv3")
                        .maxTokens(2048)
                        .temperature(0.9)
                        .build())
                .build();


        String promptStr = "";

        for (com.unfbx.chatgpt.entity.chat.Message m : messages){
            if (com.unfbx.chatgpt.entity.chat.Message.Role.USER.getName().equals(m.getRole())
                    || com.unfbx.chatgpt.entity.chat.Message.Role.SYSTEM.getName().equals(m.getRole()) ){
                promptStr += m.getContent();
            }
        }

        log.info("最终提示语：\n{}", promptStr);

        List<Text> text = new ArrayList<>();
        text.add(Text.builder()
                .role(Text.Role.USER.getName())
                .content(promptStr)
                .build());

        InPayload payload = InPayload.builder()
                .message(Message.builder()
                        .text(text)
                        .build())
                .build();

        AIChatRequest aiChatRequest = AIChatRequest.builder()
                .header(header)
                .parameter(parameter)
                .payload(payload)
                .build();

        final OpenAIEventSourceListener flistener = listener;
        sparkDeskClient.chat(new ChatListener(aiChatRequest) {
            //异常回调
            @SneakyThrows
            @Override
            public void onChatError(AIChatResponse aiChatResponse) {
                log.warn(String.valueOf(aiChatResponse));
            }
            //输出回调
            @Override
            public void onChatOutput(AIChatResponse aiChatResponse) {
                System.out.println("content: " + aiChatResponse);
                String id = System.currentTimeMillis() + "";

                String content = aiChatResponse.getPayload().getChoices().getText().stream().map(o->o.getContent()).collect(Collectors.joining());

                mockOnEvent(flistener, null, id, "", content);
            }
            //会话结束回调
            @Override
            public void onChatEnd() {
                System.out.println("当前会话结束了");

                String id = System.currentTimeMillis() + "";
                flistener.onEvent(null, id, "", "[DONE]");

            }
            //会话结束 获取token使用信息回调
            @Override
            public void onChatToken(Usage usage) {
                System.out.println("token 信息：" + usage);
            }

            private void mockOnEvent(OpenAIEventSourceListener listener, EventSource eventSource, String id, String type, String curText){
                ChatChoice choice = new ChatChoice();
                choice.setDelta(com.unfbx.chatgpt.entity.chat.Message.builder()
                        .role(com.unfbx.chatgpt.entity.chat.Message.Role.ASSISTANT).content(curText).build());

                List<ChatChoice> choices = Arrays.asList(choice);

                ChatCompletionResponse completionResponse = new ChatCompletionResponse();
                completionResponse.setChoices(choices);
                completionResponse.setId("" + System.currentTimeMillis());

                listener.onEvent(eventSource, id, type, JSON.toJSONString(completionResponse));
            }
        });
    }


    @Override
    public String getSysQuestionString( List<com.unfbx.chatgpt.entity.chat.Message> messages ) {

        //开始对话 .maxTokens(512)
        CountDownLatch latch = new CountDownLatch(1);
        ChatKefuListener listener = new ChatKefuListener(latch, messages);

        try {
            sseQuestion(messages, listener);
            latch.await();
        } catch (RuntimeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        String result = listener.getBuffer().stream().collect(Collectors.joining());

        return result;

    }



    public static void main(String[] args) throws InterruptedException {
        InHeader header = InHeader.builder().uid(UUID.randomUUID().toString().substring(0, 10)).appid(APP_ID).build();

        Parameter parameter = Parameter.builder()
                .chat(Chat.builder()
                        .domain("generalv2")
                        .maxTokens(2048)
                        .temperature(0.3)
                        .build())
                .build();


        String promptStr = "最终提示语：你是一个擅长创作公众号爆款文章专家，请根据以下要求撰写一篇文章。创作要点：生成发表至公众号的文案\n" +
                "关键词：原产地咖啡豆\n" +
                "语气：引人入胜\n" +
                "使用场景：新闻资讯\n" +
                "语言：中文\n" +
                "文章主题：黑咖啡\n" +
                "字数要求：约100字";
        log.info("最终提示语：\n{}", promptStr);

        List<Text> text = new ArrayList<>();
        text.add(Text.builder()
                .role(Text.Role.USER.getName())
                .content(promptStr)
                .build());

        InPayload payload = InPayload.builder()
                .message(Message.builder()
                        .text(text)
                        .build())
                .build();

        AIChatRequest aiChatRequest = AIChatRequest.builder()
                .header(header)
                .parameter(parameter)
                .payload(payload)
                .build();

        sparkDeskClient.chat(new ChatListener(aiChatRequest) {
            //异常回调
            @SneakyThrows
            @Override
            public void onChatError(AIChatResponse aiChatResponse) {
                log.warn(String.valueOf(aiChatResponse));
//                flistener.onFailure();
            }
            //输出回调
            @Override
            public void onChatOutput(AIChatResponse aiChatResponse) {
                System.out.println("content: " + aiChatResponse);
            }
            //会话结束回调
            @Override
            public void onChatEnd() {
                System.out.println("当前会话结束了");
            }
            //会话结束 获取token使用信息回调
            @Override
            public void onChatToken(Usage usage) {
                System.out.println("token 信息：" + usage);
            }
        });


        CountDownLatch countDownLatch = new CountDownLatch(1);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
